/*
 * Copyright (C) 2022 xuexiangjys(xuexiangjys@163.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xjh.him.activity.chat;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

import androidx.annotation.RequiresApi;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager.widget.ViewPager;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xjh.him.R;
import com.xjh.him.activity.MainActivity;
import com.xjh.him.adapter.ChatAdapter;
import com.xjh.him.adapter.entity.Chat;
import com.xjh.him.adapter.entity.ChatMessage;
import com.xjh.him.adapter.entity.Session;
import com.xjh.him.adapter.entity.SessionMember;
import com.xjh.him.common.Constant;
import com.xjh.him.core.BaseActivity;
import com.xjh.him.core.BaseFragment;
import com.xjh.him.core.netty.HandlerCallback;
import com.xjh.him.core.netty.HandlerListener;
import com.xjh.him.core.netty.NettyClient;
import com.xjh.him.core.netty.codec.Command;
import com.xjh.him.core.netty.codec.Packet;
import com.xjh.him.core.netty.dto.UserGroupMemberInviteNotifyDTO;
import com.xjh.him.databinding.ActivityChatBinding;
import com.xjh.him.dto.ChatPageSettingDTO;
import com.xjh.him.dto.UpdateNewestMsgDTO;
import com.xjh.him.dto.friend.FriendDTO;
import com.xjh.him.dto.friendgroupmsg.FriendGroupMsgDTO;
import com.xjh.him.dto.friendgroupmsg.FriendGroupMsgQueryVO;
import com.xjh.him.dto.user.UserDTO;
import com.xjh.him.dto.usergroupmsg.UserGroupMsgDTO;
import com.xjh.him.dto.usergroupmsg.UserGroupMsgQueryVO;
import com.xjh.him.fragment.emotion.classic.ClassicEmotionPanelFragment;
import com.xjh.him.fragment.emotion.unicode.UnicodeEmotionPanelFragment;
import com.xjh.him.utils.KeyboardUtils;
import com.xjh.him.utils.MMKVUtils;
import com.xjh.him.utils.Utils;
import com.xjh.him.utils.XToastUtils;
import com.xuexiang.xhttp2.callback.SimpleCallBack;
import com.xuexiang.xhttp2.exception.ApiException;
import com.xuexiang.xui.adapter.FragmentAdapter;
import com.xuexiang.xui.utils.DrawableUtils;
import com.xuexiang.xui.utils.WidgetUtils;
import com.xuexiang.xui.widget.actionbar.TitleBar;
import com.xuexiang.xui.widget.actionbar.TitleUtils;
import com.xuexiang.xutil.app.ActivityUtils;
import com.xuexiang.xutil.common.StringUtils;
import com.ypx.imagepicker.ImagePicker;
import com.ypx.imagepicker.bean.ImageItem;
import com.ypx.imagepicker.data.OnImagePickCompleteListener;

import org.xjh.tool.Checks;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;

import io.netty.channel.ChannelHandlerContext;


public class ChatActivity extends BaseActivity<ActivityChatBinding>
        implements View.OnClickListener, HandlerListener {
    public static final int PAGE_CODE = 31232;
    public static final String KEY_CHAT = "chat";
    public static final String KEY_FRIEND_DTO = "friendDTO";
    public static final String KEY_MEMBER_LIST = "memberList";

    public ChatAdapter mAdapter;
    public TitleBar titleBar;
    private Chat chat;
    private UserDTO userDTO;
    private FriendDTO friendDTO;
    private List<SessionMember> memberList;
    private int page = 1;

    @Override
    protected ActivityChatBinding viewBindingInflate(LayoutInflater inflater) {
        return ActivityChatBinding.inflate(inflater);
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initProperty();
        initTitle();
        initViews();
    }

    private void initProperty() {
        Intent intent = getIntent();
        String json = (String) MMKVUtils.get(Constant.MMKV_KEY_USER_DTO, "");
        if (!Checks.isEmpty(json)) {
            userDTO = JSON.parseObject(json, UserDTO.class);
        }
        chat = (Chat) intent.getSerializableExtra(KEY_CHAT);
        friendDTO = (FriendDTO) intent.getSerializableExtra(KEY_FRIEND_DTO);
        JSONArray jsonArray = JSON.parseArray(intent.getStringExtra(KEY_MEMBER_LIST));
        memberList = new ArrayList<>();
        if (!Checks.isEmpty(jsonArray)) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = (JSONObject) jsonArray.get(i);
                memberList.add(JSON.toJavaObject(jsonObject, SessionMember.class));
            }
        }
    }

    @SuppressLint("StringFormatMatches")
    private void refreshMemberList() {
        CountDownLatch latch = new CountDownLatch(1);
        String listMemberUrl = Utils.getWebServerApiUrl(this,
                String.format(getString(R.string.api_user_group_member_list), chat.getGroupId()));
        SimpleCallBack<List<SessionMember>> listMemberCB = new SimpleCallBack<List<SessionMember>>() {
            @Override
            public void onSuccess(List<SessionMember> list) throws Throwable {
                try {
                    memberList = list;
                } finally {
                    latch.countDown();
                }
            }

            @Override
            public void onError(ApiException e) {
                XToastUtils.toast(e.getDisplayMessage());
            }
        };
        Utils.doGet(listMemberUrl, listMemberCB);
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    protected TitleBar initTitle() {
        titleBar = TitleUtils.addTitleBarDynamic(binding.getRoot(), "", v -> {
            hideCurrentPageSoftInput();

            Intent intent = new Intent();
            List<ChatMessage> chatMessages = mAdapter.listData();
            if (!Checks.isEmpty(chatMessages)) {
                int idx = chatMessages.size()-1;
                ChatMessage chatMessage = chatMessages.get(idx);
                while (idx > 0 && ChatMessage.TYPE_USER_INVITE.equals(chatMessage.getMsgType())) {
                    chatMessage = chatMessages.get(--idx);
                }
                if (!ChatMessage.TYPE_USER_INVITE.equals(chatMessage.getMsgType())) {
                    UpdateNewestMsgDTO updateDTO = new UpdateNewestMsgDTO();
                    updateDTO.setGroupId(chat.getGroupId());
                    updateDTO.setGroupType(chat.getGroupType());
                    if (Session.GROUP_TYPE_MULTIPLE.equals(chat.getGroupType())) {
                        ChatMessage finalChatMessage = chatMessage;
                        Optional<SessionMember> optional = memberList.stream()
                                .filter(item -> item.getUserId().equals(finalChatMessage.getSenderId()))
                                .findFirst();
                        optional.ifPresent(sessionMember ->
                                updateDTO.setSenderNickname(sessionMember.getUserNickname()));
                    }
                    updateDTO.setMsgType(chatMessage.getMsgType());
                    updateDTO.setMsgContent(chatMessage.getTextMsg());
                    intent.putExtra(MainActivity.KEY_UPDATE_NEWEST_MSG_DTO, updateDTO);
                }
            }
            setResult(PAGE_CODE, intent);
            popPage();
        }).setLeftImageDrawable(DrawableUtils.getVectorDrawable(this, R.drawable.ic_menu_back));
        initTitleName();
        titleBar.addAction(new TitleBar.ImageAction(R.drawable.ic_menu_more) {

            @Override
            public void performAction(View view) {
                Map<String, Object> map = new HashMap<>();
                if (Session.GROUP_TYPE_SINGLE.equals(chat.getGroupType())) {
                    ChatPageSettingDTO settingDTO = new ChatPageSettingDTO();
                    settingDTO.setTop(chat.getTop());
                    settingDTO.setNotDisturb(false);
                    map.put(ChatSingleSettingActivity.KEY_CHAT_PAGE_SETTING_DTO, settingDTO);
                    map.put(ChatSingleSettingActivity.KEY_FRIEND_DTO, friendDTO);
                    ActivityUtils.startActivity(ChatSingleSettingActivity.class, map);
                }else if (Session.GROUP_TYPE_MULTIPLE.equals(chat.getGroupType())){
                    map.put(ChatMultipleSettingActivity.KEY_CHAT, chat);
                    map.put(ChatMultipleSettingActivity.KEY_MEMBER_LIST, JSON.toJSONString(memberList));
                    ActivityUtils.startActivity(ChatMultipleSettingActivity.class, map);
                }
            }
        });
        return titleBar;
    }

    private void initTitleName() {
        if (chat != null) {
            if (Session.GROUP_TYPE_MULTIPLE.equals(chat.getGroupType())) {
                titleBar.setTitle(chat.getGroupName() + "(" + memberList.size() + ")");
            }else {
                titleBar.setTitle(chat.getGroupName());
            }
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    protected void initViews() {
        WidgetUtils.initRecyclerView(binding.chatList, 0);

        //查询聊天组id
        if (Session.GROUP_TYPE_SINGLE.equals(chat.getGroupType())) {
            loadSingleData();
        }else if (Session.GROUP_TYPE_MULTIPLE.equals(chat.getGroupType())) {
            loadMultipleData();
        }
    }

    private void loadSingleData() {
        //查询单聊消息
        String queryHistoryUrl = Utils.getWebServerApiUrl(this, getString(R.string.api_friend_group_msg_history));
        FriendGroupMsgQueryVO queryVO = new FriendGroupMsgQueryVO();
        queryVO.setGroupId(chat.getGroupId());
        SimpleCallBack<List<FriendGroupMsgDTO>> queryHistoryCB = new SimpleCallBack<List<FriendGroupMsgDTO>>() {
            @RequiresApi(api = Build.VERSION_CODES.N)
            @Override
            public void onSuccess(List<FriendGroupMsgDTO> response) throws Throwable {
                List<ChatMessage> list = ChatActivity.this.convertMsg1(response);
                mAdapter = new ChatAdapter(ChatActivity.this, list);
                binding.chatList.setAdapter(mAdapter);
                if (list.size() > 0) {
                    page++;
                }

                initEmotionTab();
                initListener();
                recyclerScrollToBottom();
            }

            @Override
            public void onError(ApiException e) {
                XToastUtils.toast(e.getDisplayMessage());
            }
        };
        Utils.doPost(queryHistoryUrl, JSON.toJSONString(queryVO), queryHistoryCB);
    }

    private void loadMultipleData() {
        //查询群聊消息
        String listUrl = Utils.getWebServerApiUrl(this, getString(R.string.api_user_group_msg_list));
        UserGroupMsgQueryVO queryVO = new UserGroupMsgQueryVO();
        queryVO.setGroupId(chat.getGroupId());
        SimpleCallBack<List<UserGroupMsgDTO>> listCB = new SimpleCallBack<List<UserGroupMsgDTO>>() {
            @SuppressLint("NewApi")
            @Override
            public void onSuccess(List<UserGroupMsgDTO> response) throws Throwable {
                List<ChatMessage> list = convertMsg2(response);
                mAdapter = new ChatAdapter(ChatActivity.this, list);
                binding.chatList.setAdapter(mAdapter);
                if (list.size() > 0) {
                    page++;
                }

                initEmotionTab();
                initListener();
                recyclerScrollToBottom();
            }

            @Override
            public void onError(ApiException e) {
                XToastUtils.error(e.getDisplayMessage());
            }
        };
        Utils.doPost(listUrl, JSON.toJSONString(queryVO), listCB);
    }

    private List<ChatMessage> convertMsg1(List<FriendGroupMsgDTO> msgDTOList) {
        List<ChatMessage> list = new ArrayList<>();
        for (int i = msgDTOList.size()-1; i >= 0; i--) {
            list.add(ChatMessage.convertFrom(userDTO, friendDTO, msgDTOList.get(i)));
        }
        return list;
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    private List<ChatMessage> convertMsg2(List<UserGroupMsgDTO> msgDTOList) {
        List<ChatMessage> list = new ArrayList<>();
        for (int i = msgDTOList.size()-1; i >= 0; i--) {
            list.add(ChatMessage.convertFrom(userDTO, memberList, msgDTOList.get(i)));
        }
        return list;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        HandlerCallback.cancelSubscribe(this);
    }

    /**
     * 初始化表情栏
     */
    public void initEmotionTab() {
        // 填充表情栏数据
        BaseFragment[] fragments = new BaseFragment[] {
                new UnicodeEmotionPanelFragment(),
                new ClassicEmotionPanelFragment(this),
        };
        FragmentManager fm = getSupportFragmentManager();
        FragmentAdapter<BaseFragment> adapter = new FragmentAdapter<>(fm, fragments);
        binding.includeEmotion.vpEmotionPager.setOffscreenPageLimit(fragments.length - 1);
        binding.includeEmotion.vpEmotionPager.setAdapter(adapter);
        // 初始化圆点指示器
        for (int i = 0; i < fragments.length; i++) {
            View view = new View(this);
            view.setBackgroundResource(R.drawable.selector_small_round_indicator);
            view.setEnabled(false);
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(20, 20);
            if (i != 0) {
                layoutParams.leftMargin = 10;
            }
            binding.includeEmotion.llPointIndicator.addView(view, layoutParams);
        }
        // 监听切换页面动作，更新指示器
        binding.includeEmotion.vpEmotionPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            int preSelectPosition = 0;
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                LinearLayout linearLayout = binding.includeEmotion.llPointIndicator;
                linearLayout.getChildAt(preSelectPosition).setEnabled(false);
                linearLayout.getChildAt(position).setEnabled(true);
                this.preSelectPosition = position;
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    public void initListener() {
        this.setKeyboardListener();
        this.setInputMsgListener();
        this.setSendBtnListener();
        this.setMoreBtnListener();
        this.setExpressionBtnListener();
        this.setRefreshLayoutListener();

        binding.includeMore.moreImage.setOnClickListener(this);
        binding.includeMore.moreCamera.setOnClickListener(this);

        HandlerCallback.subscribe(this);
    }

    public void setRefreshLayoutListener() {
        binding.srlRefreshLayout.setOnRefreshListener(refreshLayout -> {
            String queryHistoryUrl = Utils.getWebServerApiUrl(this, getString(R.string.api_friend_group_msg_history));
            FriendGroupMsgQueryVO queryVO = new FriendGroupMsgQueryVO();
            queryVO.setGroupId(chat.getGroupId());
            queryVO.setPage(page);
            SimpleCallBack<List<FriendGroupMsgDTO>> queryHistoryCB = new SimpleCallBack<List<FriendGroupMsgDTO>>() {
                @RequiresApi(api = Build.VERSION_CODES.N)
                @Override
                public void onSuccess(List<FriendGroupMsgDTO> response) throws Throwable {
                    List<ChatMessage> list = ChatActivity.this.convertMsg1(response);
                    mAdapter.listData().addAll(0, list);
                    mAdapter.notifyItemRangeInserted(0, list.size());
                    if (list.size() > 0) {
                        page++;
                    }
                    refreshLayout.finishRefresh();
                }

                @Override
                public void onError(ApiException e) {
                    XToastUtils.toast(e.getDisplayMessage());
                    refreshLayout.finishRefresh();
                }
            };
            Utils.doPost(queryHistoryUrl, JSON.toJSONString(queryVO), queryHistoryCB);
        });
    }

    public void setKeyboardListener() {
        Activity mActivity = this;
        KeyboardUtils.addKeyboardToggleListener(mActivity, isVisible -> {
            if (isVisible) {
                KeyboardUtils.saveKeyboardHeight(mActivity);
                recyclerLayoutMoveUp();
            }else {
                recyclerLayoutMoveDown();
            }
            recyclerScrollToBottom();
        });
    }

    public void setInputMsgListener() {
        binding.inputMsg.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                String msg = binding.inputMsg.getText().toString();
                //当有文字输入后，将更多按钮切换成发送按钮
                if (!StringUtils.isEmpty(msg)) {
                    binding.btnMore.setVisibility(View.GONE);
                    binding.btnSend.setVisibility(View.VISIBLE);
                } else {
                    binding.btnMore.setVisibility(View.VISIBLE);
                    binding.btnSend.setVisibility(View.GONE);
                }
            }
        });
    }

    public void setSendBtnListener() {
        binding.btnSend.setOnClickListener((v -> {
            String textMsg = binding.inputMsg.getText().toString();
            ChatMessage chatMessage = ChatMessage.convertFromUser(
                    userDTO,
                    ChatMessage.TYPE_TEXT,
                    textMsg,
                    ""
            );
            this.sendMsg(chatMessage, "");
            binding.inputMsg.setText("");
        }));
    }

    /**
     * 发送消息
     * @param chatMessage
     */
    public Boolean sendMsg(ChatMessage chatMessage, String filePath) {
        //发送服务器
        if (Session.GROUP_TYPE_SINGLE.equals(chat.getGroupType())) {
            FriendGroupMsgDTO msgDTO = ChatMessage.convertTo(chat.getGroupId(), friendDTO.getId(), chatMessage);
            NettyClient instance = NettyClient.getInstance();
            instance.sendMsg(new Packet(
                    Command.FRIEND_GROUP_MSG_SEND, msgDTO
            ));
        }else if (Session.GROUP_TYPE_MULTIPLE.equals(chat.getGroupType())){
            UserGroupMsgDTO msgDTO = ChatMessage.convertTo(chat.getGroupId(), chatMessage);
            NettyClient instance = NettyClient.getInstance();
            instance.sendMsg(new Packet(
                    Command.USER_GROUP_MSG_SEND, msgDTO
            ));
        }
        if (!Checks.isEmpty(filePath)) {
            chatMessage.setFileUrl(filePath);
        }
        //添加消息
        mAdapter.listData().add(chatMessage);
        mAdapter.notifyItemInserted(mAdapter.getItemCount() - 1);
        this.recyclerScrollToBottom();
        return true;
    }

    public void setMoreBtnListener() {
        binding.btnMore.setOnClickListener(v -> {
            if (binding.includeMore.moreLayout.isShown()) {
                hideMoreLayout();
            }else {
                showMoreLayout();
                recyclerScrollToBottom();
            }
        });
    }

    private void hideMoreLayout() {
        binding.includeMore.moreLayout.setVisibility(View.GONE);
    }

    private void showMoreLayout() {
        if (KeyboardUtils.isSoftInputShow(this)) {
            hideCurrentPageSoftInput();
        }
        if (binding.includeEmotion.emotionLayout.isShown()) {
            hideEmotionLayout();
        }
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) binding.includeMore.moreLayout.getLayoutParams();
        layoutParams.height = KeyboardUtils.getKeyboardHeight();
        binding.includeMore.moreLayout.setVisibility(View.VISIBLE);
    }

    public void setExpressionBtnListener() {
        binding.btnExpression.setOnClickListener(v -> {
            if (!binding.includeEmotion.emotionLayout.isShown()) {
                if (binding.includeMore.moreLayout.isShown()) {
                    hideMoreLayout();
                }
                if (KeyboardUtils.isSoftInputShow(this)) {
                    recyclerLayoutMoveUp();
                    hideCurrentPageSoftInput();
                    showEmotionLayout();
                }else {
                    showEmotionLayout();
                    recyclerScrollToBottom();
                }
                // 指示器选中第一个
                binding.includeEmotion.llPointIndicator.getChildAt(0).setEnabled(true);
            }else {
                hideEmotionLayout();
                recyclerLayoutMoveDown();
            }
        });
    }

    private void showEmotionLayout() {
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) binding.includeEmotion.emotionLayout.getLayoutParams();
        layoutParams.height = KeyboardUtils.getKeyboardHeight();
        binding.includeEmotion.emotionLayout.setVisibility(View.VISIBLE);
    }

    private void hideEmotionLayout() {
        binding.includeEmotion.emotionLayout.setVisibility(View.GONE);
    }

    private void recyclerLayoutMoveUp() {
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) binding.recyclerLayout.getLayoutParams();
        layoutParams.height = binding.recyclerLayout.getHeight();
        layoutParams.weight = 0.0f;
    }

    private void recyclerLayoutMoveDown() {
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) binding.recyclerLayout.getLayoutParams();
        layoutParams.height = 0;
        layoutParams.weight = 1.0f;
    }

    public void recyclerScrollToBottom() {
        binding.chatList.scrollToPosition(mAdapter.getItemCount() - 1);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (isTouchView(binding.inputMsg, ev)) {
            if (binding.includeEmotion.emotionLayout.isShown() ||
                    binding.includeMore.moreLayout.isShown()) {
                hideMoreLayout();
                hideEmotionLayout();
                KeyboardUtils.showSoftInput(binding.inputMsg);
                recyclerLayoutMoveUp();
            }
        }else if (isTouchView(binding.chatList, ev)){
            hideMoreLayout();
            hideEmotionLayout();
            recyclerLayoutMoveDown();
            hideCurrentPageSoftInput();
        }
        return super.dispatchTouchEvent(ev);
    }

    public boolean isTouchView(View view, MotionEvent event) {
        if (view == null || event == null) {
            return false;
        }
        int[] leftTop = {0, 0};
        view.getLocationInWindow(leftTop);
        int left = leftTop[0];
        int top = leftTop[1];
        int bottom = top + view.getHeight();
        int right = left + view.getWidth();
        if (event.getRawX() > left && event.getRawX() < right
                && event.getRawY() > top && event.getRawY() < bottom) {
            return true;
        }
        return false;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.more_image:
                Utils.getWeChatPickerBuilder()
                    .setMaxCount(1)
                    .pick(this, new OnImagePickCompleteListener() {
                        @Override
                        public void onImagePickComplete(ArrayList<ImageItem> items) {
                            String uploadUrl = Utils.getSevServerApiUrl(ChatActivity.this, getString(R.string.api_img_upload));
                            String filePath = items.get(0).getPath();
                            SimpleCallBack<String> uploadCB = new SimpleCallBack<String>() {
                                @Override
                                public void onSuccess(String response) throws Throwable {
                                    ChatMessage chatMessage = ChatMessage.convertFromUser(
                                            userDTO, ChatMessage.TYPE_IMAGE, "", response);
                                    sendMsg(chatMessage, filePath);
                                }

                                @Override
                                public void onError(ApiException e) {
                                    XToastUtils.error(e.getDisplayMessage());
                                }
                            };
                            Utils.uploadFile(uploadUrl, new File(filePath), uploadCB);
                        }
                    });
                break;
            case R.id.more_camera:
                ImagePicker.takePhoto(this, null, false, new OnImagePickCompleteListener() {
                    @Override
                    public void onImagePickComplete(ArrayList<ImageItem> items) {
                        if (items != null && items.size() == 1) {
                            String uploadUrl = Utils.getSevServerApiUrl(ChatActivity.this, getString(R.string.api_img_upload));
                            String filePath = items.get(0).getPath();
                            SimpleCallBack<String> uploadCB = new SimpleCallBack<String>() {
                                @Override
                                public void onSuccess(String response) throws Throwable {
                                    ChatMessage chatMessage = ChatMessage.convertFromUser(
                                            userDTO, ChatMessage.TYPE_IMAGE, "", response);
                                    sendMsg(chatMessage, filePath);
                                }

                                @Override
                                public void onError(ApiException e) {
                                    XToastUtils.toast(e.getDisplayMessage());
                                }
                            };
                            Utils.uploadFile(uploadUrl, new File(filePath), uploadCB);
                        }
                    }
                });
                break;
        }
    }

    @SuppressLint("NewApi")
    @Override
    public Boolean consume(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof FriendGroupMsgDTO) {
            FriendGroupMsgDTO msgDTO = (FriendGroupMsgDTO) msg;
            if (!chat.getGroupId().equals(msgDTO.getFriendGroupId())) {
                return false;
            }

            ChatMessage chatMessage = ChatMessage.convertFrom(userDTO, friendDTO, msgDTO);
            mAdapter.listData().add(chatMessage);

            //刷新最新的消息
            runOnUiThread(() -> {
                mAdapter.notifyItemInserted(mAdapter.getItemCount() - 1);
                this.recyclerScrollToBottom();
            });
            return true;
        }else if (msg instanceof UserGroupMsgDTO) {
            UserGroupMsgDTO msgDTO = (UserGroupMsgDTO) msg;
            if (!chat.getGroupId().equals(msgDTO.getUserGroupId())) {
                return false;
            }

            ChatMessage chatMessage = ChatMessage.convertFrom(userDTO, memberList, msgDTO);
            mAdapter.listData().add(chatMessage);

            //刷新最新的消息
            runOnUiThread(() -> {
                mAdapter.notifyItemInserted(mAdapter.getItemCount() - 1);
                this.recyclerScrollToBottom();
            });
            return true;
        }else if (msg instanceof UserGroupMemberInviteNotifyDTO) {
            UserGroupMemberInviteNotifyDTO notifyDTO = (UserGroupMemberInviteNotifyDTO) msg;
            Optional<SessionMember> optional = memberList.stream()
                    .filter(item -> item.getUserId().equals(notifyDTO.getMemberId()))
                    .findFirst();
            SessionMember sessionMember = null;
            if (optional.isPresent()) {
                sessionMember = optional.get();
            }
            if (sessionMember == null) {
                XToastUtils.error("成员id不存在:" + notifyDTO.getMemberId());
                return true;
            }
            String memberName = (userDTO.getId().equals(notifyDTO.getMemberId())) ?
                    "你" : sessionMember.getUserNickname();
            List<ChatMessage> messageList = new ArrayList<>();
            Date current = new Date();
            for (UserGroupMemberInviteNotifyDTO.InviteUser user : notifyDTO.getUserList()) {
                ChatMessage chatMessage = new ChatMessage();
                chatMessage.setMsgType(ChatMessage.TYPE_USER_INVITE);
                chatMessage.setInviteTip(ChatMessage.getFormatInviteTip(memberName, user.getUserNickname()));
                chatMessage.setCreateTime(current);
                messageList.add(chatMessage);
            }
            int lastIdx = mAdapter.listData().size() - 1;
            mAdapter.listData().addAll(messageList);
            refreshMemberList();
            runOnUiThread(() -> {
                initTitleName();
                mAdapter.notifyItemRangeInserted(lastIdx, messageList.size());
                this.recyclerScrollToBottom();
            });
            return true;
        }
        return false;
    }
}
